﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Day4
{
    class Program
    {
        static void Main(string[] args)
        {
            demo1();
            demo2();
            demo3();
            demo4();
        }

        #region demo1
        /// <summary>
        /// 非关联嵌套，即内层Task和外层Task没有任何关系
        /// 外层的pTask运行完后，并不会等待内层的cTask，直接向下走先输出了Flag。
        /// 这种嵌套有时候相当于我们创建两个Task，但是嵌套在一起的话，
        /// 在Task比较多时会方便查找和管理，并且还可以在一个Task中途加入多个Task，让进度并行前进
        /// </summary>
        private static void demo1()
        {
            var pTask = Task.Factory.StartNew(() =>
            {
                var cTask = Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("Children task finished");
                });
                Console.WriteLine("Parent task finished");
            });
            pTask.Wait();
            Console.WriteLine("Flag");
            Console.ReadLine();
        }
        #endregion

        #region demo2
        /// <summary>
        /// 关联嵌套
        /// 就是创建有父子关系的Task
        /// 创建cTask时，加入了以参数，TaskCreationOptions.AttachedToParent
        /// 这个时候，cTask和pTask就会建立关联，cTask就会成为pTask的一部分
        /// </summary>
        private static void demo2()
        {
            var pTask = Task.Factory.StartNew(() =>
            {
                var cTask = Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("Children task finished");
                }, TaskCreationOptions.AttachedToParent);
                Console.WriteLine("Parent task finished");
            });
            pTask.Wait();
            Console.WriteLine("Flag");
            Console.ReadLine();
        }
        #endregion

        #region demo3
        private static void demo3()
        {
            Task.Factory.StartNew(() =>
            {
                var task1 = Task.Factory.StartNew<int>(() =>
                {
                    Console.WriteLine("Task 1 running");
                    return 1;
                });
                task1.Wait(); // 等待task1完成
                var task4 = Task.Factory.StartNew<int>(() =>
                {
                    Console.WriteLine("Task 2 running");
                    return task1.Result + 2;
                }).ContinueWith<int>((task) => {
                    Console.WriteLine("Task 4 running");
                    return task.Result + 4;
                });
                var task3 = Task.Factory.StartNew<int>(() =>
                {
                    Console.WriteLine("Task 3 running");
                    return task1.Result + 3;
                });
                Task.WaitAll(task3, task4); // 等待任务3和任务4完成
                var result = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine($"Task finished, the result is {task3.Result + task4.Result}");
                });
            });
            Console.ReadLine();
        }
        #endregion

        #region demo4
        /// <summary>
        /// Task的异常处理
        /// </summary>
        private static void demo4()
        {
            try
            {
                var pTask = Task.Factory.StartNew(() =>
                {
                    var cTask = Task.Factory.StartNew(() =>
                    {
                        Thread.Sleep(2000);
                        throw new Exception("cTask Error");
                        //Console.WriteLine("Children task finished");
                    });
                    throw new Exception("pTask Error");
                    //Console.WriteLine("Parent task finished");
                });
                pTask.Wait();
            }
            catch (AggregateException aex)
            {
                foreach (var ex in aex.InnerExceptions)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            Console.WriteLine("Flag");
            Console.ReadLine();
        }
        #endregion
    }
}
